/*
 * =====================================================================================
 *
 *       Filename:  bus.c
 *
 *    Description:  总线和设备实验之bus模块部分
 *
 *        Version:  1.0
 *        Created:  2015年09月23日 14时40分54秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */


#include <linux/module.h>
#include <linux/device.h>
#include <linux/string.h>
#include <linux/init.h>

MODULE_AUTHOR("guicai.ma@qq.com");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("a bus_type");

static char *Version = "V1.0.1";

/**
 * @brief 定义bus的匹配函数match
 *
 * @param dev
 * @param drv
 *
 * @return 
 */
static int my_bus_match(struct device *dev , struct device_driver *drv){
    //新版本的device的init_name不能直接操作，需要通过dev_set_name()来设定名称，通过dev_name()来获取名称
    return !strncmp(dev_name(dev) , drv->name , strlen(dev->bus->name));
}

/**
 * @brief 定义读属性操作
 *
 * @param bus
 * @param buf
 *
 * @return 
 */
static ssize_t show_attr(struct bus_type *bus , char *buf){
    printk("show bus attribute :%s\n",bus->name);
    int ret = sprintf(buf , "%s\n",Version);
    return ret;
}

/**
 * @brief 定义写属性操作
 *
 * @param bus
 * @param buf
 * @param count
 *
 * @return 
 */
static ssize_t store_attr(struct bus_type *bus ,char *buf , size_t count){
    printk("store bus attribute:%s\n",buf);
}

/**
 * @brief 初始化一个bus_attribute ，属性名称是bus_attr_$第一个参数
 *
 * @param version
 * @param S_IRUGO
 * @param show_attr
 * @param store_attr
 */
BUS_ATTR(version,S_IRUGO , show_attr,store_attr);


/**
 * 声明并初始化一个bus
 */
struct bus_type mybus = {
    .name = "my_bus",
    .match = my_bus_match
};
static void dev_release(struct device *dev){

}

/**
 * 
 * @brief 建议定义与总线同名的设备对象（并不是必要的，除非有此类需求）
 * release成员的定义是必要的
 */
struct device my_bus_dev = {
    .bus = &mybus,
    .release = dev_release
};

/**
 * @brief 导出符号到内核中，供其它模块访问使用
 *
 * @param mybus
 */
EXPORT_SYMBOL(mybus);
EXPORT_SYMBOL(my_bus_dev);

/**
 * @brief 模块初始化
 *
 * @return 
 */
static int __init bus_module_init(void)
{
    //注册总线
    bus_register(&mybus);
    //创建总线的属性文件
    if(bus_create_file(&mybus,&bus_attr_version))
        printk(KERN_NOTICE"bus create file error!\n");
    //创建一个设备 
    dev_set_name(&my_bus_dev,"my_bus_dev0");
    device_register(&my_bus_dev);
    return 0;
}

/**
 * @brief 模块卸载
 *
 * @return 
 */
static void __exit bus_module_exit(void)
{
    //注销总线
   device_unregister(&my_bus_dev);
   bus_unregister(&mybus); 
}
module_init(bus_module_init);
module_exit(bus_module_exit);
